#version 450

layout(location = 0) in vec3 fragColor;
layout(location = 1) in vec3 fragPosWorld;
layout(location = 2) in vec3 fragNormalWorld;
layout(location = 3) in vec2 fragUV;

layout(location = 0) out vec4 outColor;

struct PointLight {
    vec4 position;
    vec4 color;
    // float radius;
};

layout(set = 0, binding = 0) uniform GlobalUbo {
    mat4 projection;
    mat4 view;
    mat4 inverseView;
    vec4 ambientLightColor;
    PointLight pointLights[10];
    int numLights;
} ubo;

layout(push_constant) uniform Push {
    mat4 modelMatrix;
    mat4 normalMatrix;
} push;

void main() {
    vec3 diffuseLight = ubo.ambientLightColor.xyz * ubo.ambientLightColor.w;
    vec3 specularLight = vec3(0.0);

    vec3 surfaceNormal = normalize(fragNormalWorld);
    vec3 cameraPosWorld = ubo.inverseView[3].xyz;
    vec3 viewDir = normalize(cameraPosWorld - fragPosWorld);

    for(int i = 0; i < ubo.numLights; i++) 
    {
        vec3 distanceToLight = ubo.pointLights[i].position.xyz - fragPosWorld;
        vec3 directionToLight = normalize(distanceToLight);
        float attenuation = 1.0 / dot(distanceToLight, distanceToLight);
        vec3 intensity = ubo.pointLights[i].color.xyz * ubo.pointLights[i].color.w * attenuation;

        vec3 halfVec = normalize(directionToLight + viewDir);
        float spec = dot(surfaceNormal, halfVec);
        spec = clamp(spec, 0.0, 1.0);
        spec = pow(spec, 512.0);
        specularLight += intensity * spec;

        float diff = max(dot(surfaceNormal, directionToLight), 0.0);
        diffuseLight += intensity * diff;
    }
    vec3 rst = (diffuseLight + specularLight) * fragColor;
    outColor = vec4(rst, 1.0);
}